//
//  ZXAvoidCrashRuntime.m
//  ZXAvoidCrash
//
//  Created by 朱新明 on 2022/11/24.
//

#import "ZXAvoidCrashRuntime.h"
#import <objc/runtime.h>

@implementation ZXAvoidCrashRuntime

+ (void)exchangeInstanceMethodWithClass:(Class)anClass
                       originalSelector:(SEL)originalSel
                       swizzledSelector:(SEL)swizzledSel
{
    if (originalSel == swizzledSel) {
        return;
    }
    Class cls = anClass;
    //如果没有方法实现，则返回nil；是本类，也可能是父类的方法。
    Method originalMethod = class_getInstanceMethod(cls, originalSel);
    //本类的方法
    Method swizzledMethod = class_getInstanceMethod(cls, swizzledSel);
    [self swizzleMethodWithOriginalSelector:originalSel originalMethod:originalMethod swizzledSelector:swizzledSel swizzledMethod:swizzledMethod class:cls];
}


+ (void)exchangeClassMethodWithClass:(Class)anClass
                    originalSelector:(SEL)originalSel
                    swizzledSelector:(SEL)swizzledSel
{
    Class cls = objc_getMetaClass(class_getName(anClass));
    Method originalMethod = class_getClassMethod(cls, originalSel);
    Method swizzledMethod = class_getClassMethod(cls, swizzledSel);
    [self swizzleMethodWithOriginalSelector:originalSel originalMethod:originalMethod swizzledSelector:swizzledSel swizzledMethod:swizzledMethod class:cls];
}

+ (void)swizzleMethodWithOriginalSelector:(SEL)originalSel
                           originalMethod:(Method)originalMethod
                         swizzledSelector:(SEL)swizzledSel
                           swizzledMethod:(Method)swizzledMethod
                                    class:(Class)cls
{
    if (!swizzledMethod || !originalMethod) {
        return;
    }
    BOOL didAddMethod = class_addMethod(cls, originalSel, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if (didAddMethod)
    {
        class_replaceMethod(cls, swizzledSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    }
    else
    {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}


@end
